﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition;
using System.Reflection;
using SkypeStudio.Controls.Services;
using SkypeStudio.Framework;

namespace PongsathonKeng.SkypeStudio
{
    public interface ISkypeStudioApplication
    {
        CompositionContainer Container { get; }
        void Initialize();
    }
    class SkypeStudioApplication : ISkypeStudioApplication
    {
        public CompositionContainer Container { get; private set; }

        public SkypeStudioApplication()
        {

        }

        public void Initialize()
        {
            AggregateCatalog catalog = new AggregateCatalog();
            // Add the FARM assembly to the catalog
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            // Add the FARM.Foundation assembly to the catalog
            catalog.Catalogs.Add(new AssemblyCatalog(typeof(ISkypeApplicationService).Assembly));

            Container = new CompositionContainer(catalog);
            CompositionBatch batch = new CompositionBatch();
            batch.AddExportedValue(Container);
            Container.Compose(batch);

            IoC.GetInstance = GetInstance;
            IoC.GetAllInstances = GetAllInstances;
            IoC.BuildUp = BuildUp;
            ISkypeApplicationService skypeApplicationService = this.Container.GetExportedValue<ISkypeApplicationService>();
        }

        /// <summary>
        /// Override this to provide an IoC specific implementation.
        /// </summary>
        /// <param name="service">The service to locate.</param>
        /// <param name="key">The key to locate.</param>
        /// <returns>The located service.</returns>
        private object GetInstance(Type serviceType, string key)
        {
            var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
            var exports = Container.GetExportedValues<object>(contract);

            if (exports.Count() > 0)
                return exports.First();

            throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
        }

        /// <summary>
        /// Override this to provide an IoC specific implementation
        /// </summary>
        /// <param name="service">The service to locate.</param>
        /// <returns>The located services.</returns>
        private IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return Container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
        }

        /// <summary>
        /// Override this to provide an IoC specific implementation.
        /// </summary>
        /// <param name="instance">The instance to perform injection on.</param>
        private void BuildUp(object instance)
        {
            Container.SatisfyImportsOnce(instance);
        }



    }
}
